v3: add AST-free fastc parser backend - #28156
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b21338c635
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 06ab85dcc8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 258ca9dfdc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b5dfa43492
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3d99015d16
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4c06d76ab7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6c5caae3be
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e4ad36b31e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 88af6f593c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5428bf8549
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 290f5b72f9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 416324bfcd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 16870c1160
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9141bde2fb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e51232b2e9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4df98625a9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c19a2934db
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ed8ab5569c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c39cb9664
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f9810de3fb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ecdaffc7a5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9b9c8487e9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2460024711
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if previous == .dot || name in g.locals || name in g.functions | ||
| || name in ['print', 'println', 'bool', 'byte', 'char', 'f32', 'f64', 'i8', 'i16', 'i32', 'i64', 'int', 'isize', 'string', 'u8', 'u16', 'u32', 'u64', 'uint', 'usize', 'voidptr', 'byteptr'] { |
There was a problem hiding this comment.
Reject narrow integer casts in expressions
A valid expression such as println(u8(255) + u8(1)) reaches this allowlist even though C promotes both operands to int; the generated _Generic therefore prints 256, whereas V retains the u8 result and prints 0. The signature-level narrow-integer guard does not cover casts inside expressions, so reject these expressions or explicitly truncate arithmetic results to the V operand type.
Useful? React with 👍 / 👎.
| if should_run { | ||
| run_result := run_binary(bin_file, run_args) |
There was a problem hiding this comment.
Return after publishing C-only output
When run is combined with -o file.c or -o -, c_only validates using a temporary executable, deletes it, and publishes the C source, but this branch then tries to execute bin_file anyway. That either fails or runs a stale sibling executable whose name is file with the .c suffix removed; the complete C path correctly returns from its c_only block at driver.v:9422-9442, so FastC should do the same.
Useful? React with 👍 / 👎.
| 'voidptr' { 'voidptr' } | ||
| 'byteptr' { 'byteptr' } | ||
| 'charptr' { 'charptr' } | ||
| else { raw_type } |
There was a problem hiding this comment.
Reject undeclared parameter and return types
When an unknown V type happens to be declared by one of the generated C headers, this fallback emits it unchanged and invalid V is accepted. For example, fn show(x size_t) { println(x) } fn main() { show(1) } uses no declared V type named size_t, but <stdlib.h> supplies the C typedef, so TinyCC successfully builds and runs it; restrict this path to FastC's supported V primitive types unless a type was actually declared in the source.
Useful? React with 👍 / 👎.
| if name in functions { | ||
| return error('fastc parser does not support duplicate function `${name}` in ${path}') | ||
| } | ||
| functions[name] = true |
There was a problem hiding this comment.
Validate argument types for declared function calls
The prepass records only whether a function name exists, so C-compatible implicit conversions can let type-invalid V compile. For example, fn show(x bool) { println(x) } fn main() { show(2) } should be rejected because an integer cannot be passed as bool, but C silently converts 2 to _Bool and the FastC binary prints true; retain supported function signatures and validate calls, or reject calls whose arguments cannot be verified.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2460024711
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| functions: functions | ||
| } | ||
| gen.s.init(file, source) | ||
| return gen.run() |
There was a problem hiding this comment.
Reject scanner diagnostics before emitting C
When scanning records a recoverable lexical diagnostic, this returns generated output without ever checking gen.s.diagnostics. For example, fn main() { println('\_') } records an unknown-escape error, but the string emitter copies \_ into C and TinyCC's warnings are disabled, so FastC can compile and run source that every normal V frontend rejects. Check the scanner diagnostics after parsing and fail before publishing the generated C.
Useful? React with 👍 / 👎.
| return g.unsupported('empty if condition') | ||
| } | ||
| g.expect(.lcbr)! | ||
| g.write_line('if (${condition}) {') |
There was a problem hiding this comment.
Require boolean expressions in if conditions
When an if condition has a C-compatible non-boolean type, this emits it directly and relies on C truthiness. Thus fn main() { if 2 { println('taken') } } is rejected by V as a non-bool condition but accepted by TinyCC and prints taken; the same unchecked lowering exists for conditional loops. Track the supported expression type or reject conditions that cannot be proven boolean.
Useful? React with 👍 / 👎.
| } | ||
| expression := g.read_expression([token.Token.semicolon, token.Token.rcbr])! | ||
| g.consume_statement_end() | ||
| g.write_line('return ${expression};') |
There was a problem hiding this comment.
Validate returned expressions against the declared type
When C can implicitly convert a returned value, this accepts a V-invalid function instead of reporting a type mismatch. For example, fn value() bool { return 2 } is rejected by the V checker, but FastC emits return 2;, TinyCC converts it to _Bool, and callers observe true. Validate the expression type against g.return_type, or reject returns whose compatibility cannot be established.
Useful? React with 👍 / 👎.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2460024711
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| expression := | ||
| g.read_expression_with_prefix(name, [token.Token.semicolon, token.Token.rcbr])! | ||
| g.consume_statement_end() | ||
| g.write_line('${expression};') |
There was a problem hiding this comment.
Reject assignments with incompatible value types
When a mutable local is assigned a C-convertible but V-incompatible value, this path only validates mutability and emits the assignment unchanged. For example, mut enabled := false; enabled = 2; println(enabled) is rejected by the V checker, but FastC declares enabled as C bool, TinyCC converts 2 to true, and the invalid program compiles and prints true. Track the local's inferred type and validate assignment compatibility before emitting the statement.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d7de568a8d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return g.unsupported('narrow integer function types') | ||
| } | ||
| g.expect(.lcbr)! | ||
| is_main := name == 'main' && params.len == 0 |
There was a problem hiding this comment.
Reject value-returning main functions
When the source declares fn main() int { return 7 }, this condition recognizes it as the entry point and converts it into a valid C int main(void), while parse_return permits the value because the recorded V return type is int. The regular checker explicitly rejects any non-void main (vlib/v/checker/checker.v:896-905), but TinyCC accepts this output and produces an executable that exits with 7, so FastC accepts invalid V; require return_type == 'void' when recognizing main.
Useful? React with 👍 / 👎.
| start := g.read_expression([token.Token.dotdot])! | ||
| start_type := fastc_normalize_inferred_type(g.last_expression_type) | ||
| g.expect(.dotdot)! | ||
| end := g.read_expression([token.Token.lcbr])! | ||
| g.expect(.lcbr)! |
There was a problem hiding this comment.
Validate range-bound types before emitting C
When a range has non-integer or mismatched bounds, such as for i in 0.0 .. 2.0 { println(1) }, both expressions are read but their inferred types are never checked before emitting a C loop. TinyCC accepts and executes that floating-point loop, whereas the normal checker rejects non-integer ranges and mismatched bounds in vlib/v/checker/for.v:72-85; verify that both bounds have compatible integer types before generating the loop.
Useful? React with 👍 / 👎.
| fn fastc_common_arithmetic_type(left string, right string) string { | ||
| if left == right { | ||
| return left |
There was a problem hiding this comment.
Reject arithmetic on non-numeric operands
When both operands have the same non-numeric type, this returns that type without checking whether the operator supports it. For example, println(true + false) is invalid V, but FastC infers bool, emits the expression unchanged, and C promotes the booleans to int, so TinyCC accepts it and prints 1; restrict arithmetic inference to numeric operand types instead of accepting every equal pair.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ed082fefce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // dispatch preserves V's bool type when no operator requires promotion. | ||
| .key_true { '((bool)true)' } | ||
| .key_false { '((bool)false)' } | ||
| .key_nil { 'NULL' } |
There was a problem hiding this comment.
Reject nil expressions outside unsafe blocks
When a pointer-taking function is called with nil outside unsafe, this unconditionally emits NULL without tracking unsafe nesting. For example, fn show(p &int) { println(*p) } fn main() { show(nil) } is rejected by the standard checker because nil is only allowed in unsafe code, but FastC's signature check accepts nil for int* and TinyCC builds a binary that dereferences NULL. Track unsafe-block context and reject .key_nil outside it.
Useful? React with 👍 / 👎.
| return g.unsupported('main function returning `${return_type}`') | ||
| } | ||
| g.expect(.lcbr)! | ||
| is_main := name == 'main' && params.len == 0 |
There was a problem hiding this comment.
Reject every parameterized main declaration
Fresh evidence after the no-argument return check is that a parameterized main bypasses both validations because it is classified as an ordinary function here, even though its emitted C name remains main. Thus fn main(code int) int { return code } becomes int main(int code), which TinyCC accepts and invokes, while the V checker rejects both the argument and return value. Validate the signature whenever name == 'main', regardless of parameter count.
Useful? React with 👍 / 👎.
| .key_nil { 'NULL' } | ||
| .key_likely, .key_unlikely { '' } | ||
| .semicolon { ';' } | ||
| else { g.tok.str() } |
There was a problem hiding this comment.
Reject bitwise negation of non-integer values
When an expression contains .bit_not, the token falls through this generic passthrough and the print-call validator permits the resulting unknown inferred type. Consequently println(~true) is emitted as C, where _Bool is promoted to int and TinyCC prints -2, whereas V rejects bitwise negation of a boolean. Handle .bit_not with integer type validation or reject it from this lane.
Useful? React with 👍 / 👎.
| return g.unsupported('statement `${g.token_source()}`') | ||
| } | ||
| g.consume_statement_end() | ||
| g.write_line('${expression};') |
There was a problem hiding this comment.
Reject value-only expression statements
When a statement is a pure value expression, such as fn main() { 1 }, this path treats any nonempty expression as valid and emits 1;. TinyCC accepts that statement, so FastC compiles source that the V parser rejects with expression evaluated but not used; restrict expression statements to supported calls, assignments, and mutation expressions.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57f482c7bd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } else if _ := fastc_primitive_c_type(name) { | ||
| if call_args.len != 1 { | ||
| return g.unsupported('cast `${name}` with ${call_args.len} arguments') | ||
| } |
There was a problem hiding this comment.
Lower primitive casts to valid C syntax
When a direct-eligible program uses a supported cast such as println(int(1.2)) or value := i64(1), this branch accepts the call, but token emission leaves it as int(1.2)/i64(1). Those are V functional-cast spellings, not valid GNU C expressions, so TinyCC rejects otherwise valid V. Rewrite these calls as C casts (for example, ((int)(1.2))) before validation.
Useful? React with 👍 / 👎.
| if actual == 'integer literal' { | ||
| return fastc_is_integer_type(expected) |
There was a problem hiding this comment.
Preserve integer-literal signedness during compatibility checks
Fresh evidence after argument and assignment type validation was added is that every integer literal is still accepted for every integer target, including negative literals for unsigned types. For example, fn take(x u32) { println(x) } fn main() { take(-1) } is rejected by the normal checker, but FastC infers -1 as integer literal, accepts it here, and TinyCC converts it to 4294967295. Retain literal signedness/value when checking compatibility and reject implicit negative-to-unsigned conversions.
Useful? React with 👍 / 👎.
| condition := g.read_expression([token.Token.semicolon])! | ||
| g.require_boolean_condition('for')! | ||
| g.expect(.semicolon)! | ||
| update := g.read_expression([token.Token.lcbr])! |
There was a problem hiding this comment.
Validate C-style loop update mutations
Fresh evidence after ordinary assignment validation was added is that the C-style for update is parsed directly as an expression and bypasses the same mutability and assignment-type checks. Thus an update such as value = 2 where value was declared immutable, or assigning an integer to a mutable bool, is emitted into the C for header and accepted through C conversion even though V rejects it. Validate the update as a mutation statement before emitting it.
Useful? React with 👍 / 👎.
| name := tokens[i].lit | ||
| if signature := g.functions[name] { |
There was a problem hiding this comment.
Reject calls to the main function
When source code calls main(), its collected signature enters this ordinary declared-function path, so FastC emits a recursive C call that TinyCC accepts. The standard V checker explicitly rejects calling main; a program such as fn main() { main() } therefore changes from a compile-time diagnostic to unbounded recursion and eventual stack exhaustion. Special-case name == 'main' before accepting declared calls.
Useful? React with 👍 / 👎.
Summary
fastcin the main-bhelpArchitecture
source -> scanner -> fastc parser/C emitter -> TinyCCFastC does not construct or consume a flat AST and never falls back to V1 or a V3 AST backend.
Validation
./v -g -keepc -o ./vnew cmd/v./vnew -silent vlib/v3/gen/fastc/fastc_test.v./vnew -silent vlib/v3/tests/fastc_backend_test.v./vnew -run-only "*fastc*" -silent cmd/v/macos_v3_test.v./vnew -silent vlib/v/pref/pref_test.v./vnew check-md vlib/v3/README.md./vnew -b fastc -o <tmp>/hello examples/hello_world.v, then ran it successfully./vnew -silent -b fastc -os linux -o <tmp>/hello_linux.c examples/hello_world.v./vnew -silent vlib/v/compiler_errors_test.v: 1,612 passed, 7 pre-existing failures, 1 skipped